#ifndef MATRIXOPTIMIZER_H
#define MATRIXOPTIMIZER_H

#include <vector>
#include <map>
#include <string>
#include <memory>
#include <set>
#include <unordered_map>
#include <queue>
#include <functional>
#include "ASTNode.h"

// 矩陣數據結構
struct MatrixInfo {
    std::string name;
    int rows;
    int cols;
    std::string dataType;  // "int", "float", "double"
    bool isSparse;
    bool isSymmetric;
    bool isTriangular;
    std::vector<std::string> accessPatterns;  // 訪問模式
    std::map<std::string, std::string> properties;  // 其他屬性
};

// 矩陣運算模式識別
struct MatrixPattern {
    std::string patternType;  // "add", "multiply", "transpose", "block", "lu", "qr", "svd"
    std::vector<ASTNode*> nodes;
    int rows;
    int cols;
    bool isOptimizable;
    double estimatedComplexity;  // 估算複雜度
    std::vector<std::string> optimizationStrategies;  // 適用的優化策略
};

// 矩陣塊結構
struct MatrixBlock {
    int startRow;
    int startCol;
    int endRow;
    int endCol;
    std::vector<ASTNode*> operations;
    std::string blockType;  // "dense", "sparse", "diagonal"
    double sparsity;  // 稀疏度
};

// 優化統計
struct OptimizationStats {
    int constantFoldingCount;
    int loopFusionCount;
    int memoryAccessOptimizationCount;
    int registerReuseCount;
    int blockOptimizationCount;
    int vectorizationCount;
    int parallelizationCount;
    int cacheOptimizationCount;
    int numericalStabilityCount;
    double totalOptimizationGain;  // 總優化收益
};

// 性能分析指標
struct PerformanceMetrics {
    int operationCount;
    int memoryAccessCount;
    int cacheMissCount;
    int registerUsage;
    double estimatedTime;
    double flops;  // 浮點運算次數
    double memoryBandwidth;  // 內存帶寬使用
    double cacheEfficiency;  // 緩存效率
};

// 代碼生成優化
struct CodeGenOptimization {
    std::string optimizationType;
    std::vector<std::string> generatedCode;
    std::map<std::string, std::string> registerMapping;
    std::vector<std::string> memoryAccessPatterns;
    double estimatedPerformanceGain;
};

// 矩陣優化器類
class MatrixOptimizer {
private:
    // 核心數據結構
    std::vector<MatrixPattern> detectedPatterns;
    std::vector<MatrixBlock> matrixBlocks;
    std::unordered_map<std::string, MatrixInfo> matrixRegistry;
    OptimizationStats stats;
    
    // 優化配置
    int optimizationLevel;
    std::map<std::string, bool> enabledOptimizations;
    std::map<std::string, double> optimizationWeights;
    
    // 性能分析器
    std::unordered_map<std::string, PerformanceMetrics> performanceMetrics;
    
    // 代碼生成優化
    std::vector<CodeGenOptimization> codeGenOptimizations;
    
    // 高級優化算法
    struct AdvancedOptimization {
        std::string name;
        std::function<void(ASTNode*)> optimizer;
        double complexity;
        double expectedGain;
        
        AdvancedOptimization(const std::string& n, std::function<void(ASTNode*)> opt, double comp, double gain)
            : name(n), optimizer(opt), complexity(comp), expectedGain(gain) {}
    };
    std::vector<AdvancedOptimization> advancedOptimizers;
    
    // 輔助函數
    bool isMatrixOperation(ASTNode* node);
    bool isMatrixAddition(ASTNode* node);
    bool isMatrixMultiplication(ASTNode* node);
    bool isMatrixTranspose(ASTNode* node);
    bool isMatrixBlockOperation(ASTNode* node);
    bool isMatrixDecomposition(ASTNode* node);
    bool isMatrixInverse(ASTNode* node);
    
    // 新增輔助函數
    int estimateMatrixSize(ASTNode* node);
    std::vector<ASTNode*> decomposeMatrix(ASTNode* node, int parts);
    int determineOptimalBlockSize(ASTNode* node);
    std::vector<MatrixBlock> decomposeIntoBlocks(ASTNode* node, int blockSize);
    bool isSparseMatrix(ASTNode* node);
    bool isTriangularMatrix(ASTNode* node);
    bool isSymmetricMatrix(ASTNode* node);
    void optimizeSparseStorage(ASTNode* node);
    void optimizeSparseComputation(ASTNode* node);
    void optimizeTriangularStorage(ASTNode* node);
    void optimizeTriangularComputation(ASTNode* node);
    void optimizeSymmetricStorage(ASTNode* node);
    void optimizeSymmetricComputation(ASTNode* node);
    void analyzeBlockStructure(ASTNode* node);
    void optimizeBlockLayout(ASTNode* node);
    void optimizeBlockComputation(ASTNode* node);
    void optimizeBlockComputation(MatrixBlock* block);
    
    // 模式檢測
    MatrixPattern detectMatrixPattern(ASTNode* node);
    void detectMatrixPatterns(ASTNode* root);
    void analyzeMatrixAccessPatterns(ASTNode* node);
    void identifyOptimizationOpportunities(ASTNode* node);
    
    // 基礎優化策略
    void optimizeMatrixAddition(ASTNode* node);
    void optimizeMatrixMultiplication(ASTNode* node);
    void optimizeMatrixTranspose(ASTNode* node);
    void optimizeMatrixBlock(ASTNode* node);
    
    // 高級優化策略
    void optimizeStrassenMultiplication(ASTNode* node);
    void optimizeCoppersmithWinograd(ASTNode* node);
    void optimizeBlockMatrixMultiplication(ASTNode* node);
    void optimizeSparseMatrixOperations(ASTNode* node);
    void optimizeTriangularMatrixOperations(ASTNode* node);
    void optimizeSymmetricMatrixOperations(ASTNode* node);
    
    // 循環優化
    void optimizeLoopFusion(ASTNode* node);
    void optimizeLoopUnrolling(ASTNode* node);
    void optimizeLoopTiling(ASTNode* node);
    void optimizeLoopVectorization(ASTNode* node);
    void optimizeLoopParallelization(ASTNode* node);
    
    // 內存訪問優化
    void optimizeMemoryAccess(ASTNode* node);
    void optimizeCacheLocality(ASTNode* node);
    void optimizeMemoryAlignment(ASTNode* node);
    void optimizeMemoryHierarchy(ASTNode* node);
    void optimizeDataLayout(ASTNode* node);
    
    // 寄存器優化
    void optimizeRegisterAllocation(ASTNode* node);
    void optimizeRegisterReuse(ASTNode* node);
    void optimizeRegisterSpilling(ASTNode* node);
    void optimizeSIMDRegisters(ASTNode* node);
    
    // 常量優化
    void optimizeConstantMatrix(ASTNode* node);
    void optimizeIdentityMatrix(ASTNode* node);
    void optimizeZeroMatrix(ASTNode* node);
    void optimizeDiagonalMatrix(ASTNode* node);
    
    // 並行化優化
    void optimizeParallelization(ASTNode* node);
    void optimizeVectorization(ASTNode* node);
    void optimizeSIMD(ASTNode* node);
    void optimizeOpenMP(ASTNode* node);
    void optimizeCUDA(ASTNode* node);
    
    // 塊優化
    void optimizeBlockMatrix(ASTNode* node);
    void optimizeBlockMultiplication(ASTNode* node);
    void optimizeBlockAddition(ASTNode* node);
    void optimizeBlockDecomposition(ASTNode* node);
    
    // 數值穩定性優化
    void optimizeNumericalStability(ASTNode* node);
    void optimizeConditioning(ASTNode* node);
    void optimizePrecision(ASTNode* node);
    void optimizeErrorAnalysis(ASTNode* node);
    
    // 代碼生成優化
    void generateOptimizedCode(ASTNode* node);
    void generateSIMDCode(ASTNode* node);
    void generateParallelCode(ASTNode* node);
    void generateBlockCode(ASTNode* node);
    void generateCacheOptimizedCode(ASTNode* node);
    
    // 性能分析
    void analyzePerformance(ASTNode* node);
    void estimateComplexity(ASTNode* node);
    void calculateMemoryAccess(ASTNode* node);
    void estimateCacheBehavior(ASTNode* node);
    
    // 優化決策
    std::vector<std::string> selectOptimizationStrategies(ASTNode* node);
    double calculateOptimizationBenefit(ASTNode* node, const std::string& strategy);
    bool shouldApplyOptimization(ASTNode* node, const std::string& strategy);
    
    // 初始化函數
    void initializeOptimizations();
    void initializeAdvancedOptimizers();
    void initializePerformanceModels();

public:
    MatrixOptimizer();
    ~MatrixOptimizer();
    
    // 主要優化接口
    void optimize(ASTNode* root);
    void optimizeMatrixOperations(ASTNode* root);
    void optimizeMatrixPatterns(ASTNode* root);
    
    // 高級優化接口
    void applyAdvancedOptimizations(ASTNode* root);
    void optimizeForTargetArchitecture(ASTNode* root, const std::string& arch);
    void optimizeForPerformanceProfile(ASTNode* root, const std::string& profile);
    
    // 統計信息
    OptimizationStats getOptimizationStats() const;
    void printOptimizationStats() const;
    void resetStats();
    
    // 性能分析
    PerformanceMetrics getPerformanceMetrics(const std::string& operationName) const;
    void printPerformanceReport() const;
    void generatePerformanceReport(const std::string& filename) const;
    
    // 優化配置
    void setOptimizationLevel(int level);
    void enableOptimization(const std::string& optName, bool enable);
    bool isOptimizationEnabled(const std::string& optName) const;
    void setOptimizationWeight(const std::string& optName, double weight);
    
    // 代碼生成優化
    std::vector<CodeGenOptimization> getCodeGenOptimizations() const;
    void generateOptimizedAssembly(ASTNode* node, std::vector<std::string>& assembly);
    void generateOptimizedC(ASTNode* node, std::vector<std::string>& cCode);
    
    // 矩陣註冊和管理
    void registerMatrix(const std::string& name, const MatrixInfo& info);
    MatrixInfo getMatrixInfo(const std::string& name) const;
    void updateMatrixProperties(const std::string& name, const std::map<std::string, std::string>& properties);
    
    // 優化建議
    std::vector<std::string> getOptimizationSuggestions(ASTNode* node) const;
    void printOptimizationSuggestions(ASTNode* node) const;
    
    // 驗證和測試
    bool validateOptimization(ASTNode* original, ASTNode* optimized) const;
    void testOptimizationCorrectness(ASTNode* node);
    
private:
    void applyOptimizations(ASTNode* node);
    void applyAdvancedOptimizers(ASTNode* node);
    void updatePerformanceMetrics(ASTNode* node, const std::string& operation);
};

// 矩陣運算檢測器
class MatrixOperationDetector {
private:
    std::vector<std::string> matrixKeywords;
    std::vector<std::string> matrixOperations;
    std::vector<std::string> matrixFunctions;
    std::map<std::string, std::string> operationPatterns;
    
public:
    MatrixOperationDetector();
    bool isMatrixVariable(const std::string& varName);
    bool isMatrixOperation(const std::string& operation);
    bool isMatrixFunction(const std::string& funcName);
    void addMatrixKeyword(const std::string& keyword);
    void addMatrixOperation(const std::string& operation);
    void addMatrixFunction(const std::string& function);
    std::string getOperationPattern(const std::string& operation) const;
};

// 矩陣性能分析器
class MatrixPerformanceAnalyzer {
private:
    struct PerformanceMetrics {
        int operationCount;
        int memoryAccessCount;
        int cacheMissCount;
        int registerUsage;
        double estimatedTime;
        double flops;
        double memoryBandwidth;
        double cacheEfficiency;
        std::map<std::string, double> detailedMetrics;
    };
    
    std::map<std::string, PerformanceMetrics> metrics;
    std::map<std::string, double> performanceModels;
    
public:
    MatrixPerformanceAnalyzer();
    void analyzeMatrixOperation(ASTNode* node);
    PerformanceMetrics getMetrics(const std::string& operationName) const;
    void printPerformanceReport() const;
    void resetMetrics();
    void setPerformanceModel(const std::string& operation, double complexity);
    double estimatePerformance(const std::string& operation, int size) const;
};

// 矩陣代碼生成器
class MatrixCodeGenerator {
private:
    std::map<std::string, std::vector<std::string>> codeTemplates;
    std::map<std::string, std::string> registerMappings;
    std::vector<std::string> generatedCode;
    
public:
    MatrixCodeGenerator();
    void generateMatrixCode(ASTNode* node, std::vector<std::string>& code);
    void generateSIMDCode(ASTNode* node, std::vector<std::string>& code);
    void generateParallelCode(ASTNode* node, std::vector<std::string>& code);
    void generateBlockCode(ASTNode* node, std::vector<std::string>& code);
    void addCodeTemplate(const std::string& operation, const std::vector<std::string>& template_);
    std::vector<std::string> getGeneratedCode() const;
};

#endif // MATRIXOPTIMIZER_H 